//File Header
//////////////////////////////////////////////////////////////////////////////
//
//                     Copyright Yuriy Silvestrov 2007
//
////////////////////////////////////////////////////////////////////////////////
//
// This file "XsdTraversor"
// part of XSD Configuration Section Generator
// Started by "yuriy@silvestrov.com" on 3/1/2007
// Last edit by "$Author$" on $Date$
//
////////////////////////////////////////////////////////////////////////////////
//
// Change log ()
//
//
//
////////////////////////////////////////////////////////////////////////////////

using System.Xml.Schema;

namespace XsdConfigSection
{
	///<summary>
	///</summary>
	public class XsdTraversor
	{
		#region attributes

		private XmlSchemaSet schemaSet;

		#endregion attributes

		#region constructors

		public XsdTraversor(XmlSchemaSet schemaSet)
		{
			this.schemaSet = schemaSet;
			if (!schemaSet.IsCompiled)
			{
				schemaSet.Compile();
			}
		}


		public XsdTraversor(XmlSchema schema)
		{
			schemaSet = new XmlSchemaSet();
			schemaSet.Add(schema);
			schemaSet.Compile();
		}

		#endregion constructors

		#region properites

		public XmlSchemaSet SchemaSet
		{
			get { return schemaSet; }
			set { schemaSet = value; }
		}

		#endregion properites

		#region events and delegates
		public delegate void TraversalDelegate(XmlSchemaParticle particle);
		public delegate object[] TraversalDelegateParameters(XmlSchemaParticle particle, params object[] list);
		#endregion events and delegates

		#region methods

		public void Traverse(TraversalDelegate develop)
		{
			foreach (XmlSchema schema in schemaSet.Schemas())
			{
				foreach (XmlSchemaType type in schema.SchemaTypes.Values)
				{
					XmlSchemaComplexType complexType;
					complexType = type as XmlSchemaComplexType;
					if (complexType != null)
						TraverseParticle(complexType.ContentTypeParticle, develop);
				}

				foreach (XmlSchemaElement el in schema.Elements.Values)
					TraverseParticle(el, develop);
			}
		}

		private static void TraverseParticle(XmlSchemaParticle particle, TraversalDelegate develop)
		{
			develop(particle);

			if (particle is XmlSchemaElement)
			{
				XmlSchemaElement elem = particle as XmlSchemaElement;

				if (elem.RefName.IsEmpty)
				{
					XmlSchemaType type = elem.ElementSchemaType;
					XmlSchemaComplexType complexType = type as XmlSchemaComplexType;
					if (complexType != null && complexType.Name == null)
						TraverseParticle(complexType.ContentTypeParticle, develop);
				}
			}
			else if (particle is XmlSchemaGroupBase)
			{
				//xs:all, xs:choice, xs:sequence
				XmlSchemaGroupBase baseParticle = particle as XmlSchemaGroupBase;
				foreach (XmlSchemaParticle subParticle in baseParticle.Items)
					TraverseParticle(subParticle, develop);
			}
		}

		#endregion properites

		#region helper functions

		#endregion helper functions
	}
}